package webhook

import (
	"bytes"
	"context"
	"encoding/json"
	"log"
	"strings"

	"gitee.com/daofeixian/dfx_golang_toolset/sendmsg"
	"gitee.com/daofeixian/dfx_golang_toolset/utils"
	lark "github.com/larksuite/oapi-sdk-go/v3"
	larkcontact "github.com/larksuite/oapi-sdk-go/v3/service/contact/v3"
)

// 常量定义
const (
	TagText = "text"
	TagAt   = "at"
	TagLink = "a"
	TagImg  = "img"

	MsgTypeText = "text"
	MsgTypePost = "post"

	DefaultFailureMsg = "模板渲染失败"
	UserIdType        = "user_id"
	ContentType       = "application/json"
)

// FeishuWebhook 飞书 Webhook 客户端
// 用于向飞书发送消息，支持文本和富文本格式，并可启用@用户功能。
type FeishuWebhook struct {
	ATEnable   bool   // 是否启用@功能
	APPID      string // 飞书应用ID
	APPSECRET  string // 飞书应用密钥
	PostUrlKey string // POST消息中URL字段的键名
	PostTitle  string // POST消息标题
}

// FeishuUserResponse 飞书用户查询响应结构体
// 表示通过手机号批量获取飞书用户ID的响应数据结构。
type FeishuUserResponse struct {
	Code int    `json:"code"` // 响应状态码
	Msg  string `json:"msg"`  // 响应消息描述
	Data []struct {
		Mobile string `json:"mobile"`  // 用户手机号
		UserID string `json:"user_id"` // 用户ID
	} `json:"data"` // 用户数据列表
}

// NewFeishuWebhook 创建新的飞书Webhook客户端实例
// 参数:
//   - appid: 飞书应用ID
//   - appsecret: 飞书应用密钥
//   - ATEnable: 是否启用@用户功能
//
// 返回值:
//   - *FeishuWebhook: 新创建的飞书Webhook客户端实例
func NewFeishuWebhook(appid, appsecret string, ATEnable bool) *FeishuWebhook {
	return &FeishuWebhook{
		APPID:     appid,
		APPSECRET: appsecret,
		ATEnable:  ATEnable,
	}
}

// SendMsg 发送消息到飞书
// 根据消息类型构建对应的消息体并发送到指定的Webhook地址。
// 参数:
//   - sendinfo: 包含发送信息的结构体，包括URL、消息内容、模板、手机号等
//
// 返回值:
//   - error: 发送过程中可能发生的错误
func (f *FeishuWebhook) SendMsg(ctx context.Context, sendinfo *sendmsg.SendInfo) error {

	mapMethod := make(map[string]string)
	if f.ATEnable {

		client := lark.NewClient(f.APPID, f.APPSECRET)
		// 创建请求对象
		req := larkcontact.NewBatchGetIdUserReqBuilder().
			UserIdType(UserIdType).
			Body(larkcontact.NewBatchGetIdUserReqBodyBuilder().
				Emails([]string{}).
				Mobiles(sendinfo.PhoneNumbers).
				IncludeResigned(false).
				Build()).
			Build()

		// 发起请求
		resp, err := client.Contact.V3.User.BatchGetId(context.Background(), req)

		// 处理错误
		if err != nil {
			log.Println("Error:", err)
			return err
		}

		// 遍历用户列表，仅当user_id存在时才添加到mapMethod中
		for _, v := range resp.Data.UserList {
			// if v.UserId == nil {
			// 	continue
			// }
			if v.UserId != nil {
				mapMethod[*v.Mobile] = *v.UserId
			}

		}
	}

	msgMap := make(map[string]interface{})
	switch sendinfo.MsgType {
	case MsgTypeText:
		msgMap["msg_type"] = MsgTypeText
		msgMap["content"] = NewFeishuTextMsg(sendinfo.Msg, sendinfo.Template, mapMethod)
	case MsgTypePost:
		msgMap["msg_type"] = MsgTypePost
		msgMap["content"] = NewFeishuPostMsg(f.PostTitle, sendinfo.Msg, sendinfo.Template, mapMethod, f.PostUrlKey)
	}
	jsonBody, err := json.Marshal(msgMap)
	if err != nil {
		return err
	}
	log.Printf("Feishu webhook request: %s", string(jsonBody))

	resqBody, err := utils.HttpDo(ctx, sendinfo.Url, "POST", bytes.NewBuffer(jsonBody), map[string]interface{}{"Content-Type": ContentType})
	if err != nil {
		log.Printf("Feishu webhook request failed: %v", err)
		return err
	}
	log.Printf("Feishu webhook response: %s", string(resqBody))
	return nil
}

// FeishuTextMsg 飞书文本消息结构
// 用于表示飞书文本消息的内容。
type FeishuTextMsg struct {
	Text string `json:"text"` // 文本内容
}

// NewFeishuTextMsg 创建飞书文本消息
// 使用模板渲染内容，并在启用@功能时添加@用户信息。
// 参数:
//   - content: 原始消息内容
//   - temptext: 模板字符串
//   - userid: 手机号与用户ID的映射关系
//
// 返回值:
//   - *FeishuTextMsg: 构造好的文本消息对象
func NewFeishuTextMsg(content string, temptext string, userid map[string]string) *FeishuTextMsg {
	content = JsonDataToTemplate(content, temptext)
	if content == "" {
		content = DefaultFailureMsg
	}

	if len(userid) > 0 {
		var atString strings.Builder
		for mobile, userID := range userid {
			atString.WriteString("<at user_id=\"")
			atString.WriteString(userID)
			atString.WriteString("\">")
			atString.WriteString(mobile)
			atString.WriteString("</at> ")
		}
		content = content + " " + atString.String()
	}

	return &FeishuTextMsg{
		Text: content,
	}
}

// FeishuPostMsg 飞书富文本消息结构
// 用于表示飞书富文本消息的整体结构。
type FeishuPostMsg struct {
	Post FeishuPost `json:"post"` // 富文本内容
}

// FeishuPost 飞书POST消息结构
// 表示飞书富文本中的语言版本内容。
type FeishuPost struct {
	ZHCN FeishuZhCN `json:"zh_cn"` // 中文内容
}

// NewFeishuPostMsg 创建飞书富文本消息
// 参数:
//   - title: 消息标题
//   - content: 原始内容
//   - temptext: 模板字符串
//   - mobile: 手机号与用户ID的映射
//   - urlKey: URL字段的键名
//
// 返回值:
//   - *FeishuPostMsg: 构造好的富文本消息对象
func NewFeishuPostMsg(title, content, temptext string, mobile map[string]string, urlKey string) *FeishuPostMsg {
	return NewFeishuZhCNMsg(title, content, temptext, mobile, urlKey)
}

// FeishuZhCN 飞书中文消息结构
// 表示飞书富文本消息中的中文内容部分。
type FeishuZhCN struct {
	Title       string                `json:"title"`   // 消息标题
	ContentMaps [][]map[string]string `json:"content"` // 内容行数组，每行包含多个元素
}

// NewFeishuZhCNMsg 创建飞书富文本消息
// 解析JSON内容并构建包含文本、链接和@用户的富文本消息。
// 参数:
//   - title: 消息标题
//   - content: 原始内容
//   - temptext: 模板字符串
//   - mobile: 手机号与用户ID的映射
//   - urlKey: URL字段的键名
//
// 返回值:
//   - *FeishuPostMsg: 构造好的富文本消息对象
func NewFeishuZhCNMsg(title, content, temptext string, mobile map[string]string, urlKey string) *FeishuPostMsg {
	strMap := make(map[string]interface{})
	if err := json.Unmarshal([]byte(content), &strMap); err != nil {
		log.Printf("解析JSON数据错误: %v, 原始数据: %s", err, content)
		return &FeishuPostMsg{
			Post: FeishuPost{
				ZHCN: FeishuZhCN{
					Title:       title,
					ContentMaps: [][]map[string]string{{{"tag": TagText, "text": DefaultFailureMsg}}},
				},
			},
		}
	}

	// 创建一行内容，包含文本、链接和@用户
	contentRow := make([]map[string]string, 0)

	// 添加文本内容
	contentRow = append(contentRow, NewFeishuTextMapMsg(content, temptext)...)

	// 添加链接
	if url, ok := strMap[urlKey]; ok && url != nil {
		if urlStr, ok := url.(string); ok && urlStr != "" {
			contentRow = append(contentRow, FileshuAlabelMapMsg("请查看", urlStr)...)
		}
	}

	// 添加@用户
	contentRow = append(contentRow, NewFileshuAtMapMsg(mobile)...)

	// 将这一行内容包装成二维数组
	contentMaps := [][]map[string]string{contentRow}

	return &FeishuPostMsg{
		Post: FeishuPost{
			ZHCN: FeishuZhCN{
				Title:       title,
				ContentMaps: contentMaps,
			},
		},
	}
}

// FileshuAlabelMapMsg 创建链接消息
// 参数:
//   - text: 链接显示文本
//   - href: 链接地址
//
// 返回值:
//   - []map[string]string: 包含链接标签的Map切片
func FileshuAlabelMapMsg(text, href string) []map[string]string {
	return []map[string]string{{
		"tag":  TagLink,
		"text": text,
		"href": href,
	}}
}

// FeishuImageMapMsg 创建图片消息
// 参数:
//   - imageKey: 图片资源标识符
//
// 返回值:
//   - []map[string]string: 包含图片标签的Map切片
func FeishuImageMapMsg(imageKey string) []map[string]string {
	return []map[string]string{{
		"tag":       TagImg,
		"image_key": imageKey,
	}}
}

// NewFeishuTextMapMsg 创建文本Map消息
// 使用模板渲染文本内容。
// 参数:
//   - content: 原始内容
//   - temptext: 模板字符串
//
// 返回值:
//   - []map[string]string: 包含文本标签的Map切片
func NewFeishuTextMapMsg(content, temptext string) []map[string]string {
	text := JsonDataToTemplate(content, temptext)
	if text == "" {
		text = DefaultFailureMsg
	}
	return []map[string]string{{
		"tag":  TagText,
		"text": text,
	}}
}

// NewFileshuAtMapMsg 创建@用户消息
// 参数:
//   - mobile: 手机号与用户ID的映射
//
// 返回值:
//   - []map[string]string: 包含@标签的Map切片
func NewFileshuAtMapMsg(mobile map[string]string) []map[string]string {
	if len(mobile) == 0 {
		return nil
	}

	mapMsgs := make([]map[string]string, 0, len(mobile))
	for userName, userID := range mobile {
		mapMsgs = append(mapMsgs, map[string]string{
			"tag":       TagAt,
			"user_id":   userID,
			"user_name": userName,
		})
	}
	return mapMsgs
}
